#include "protocol.h"
#include <stdio.h>
#include <string.h>

protocolfunc ProtoColFindFunc(u8 funcode_l, u8 funcode_h);
ProtocolStru g_Protocol = {0};

printfFun myPrint;

u8 messageSubscribeid = 5;
u8 messageSubscribepority = 0;
u8 messagePublishid = 3;
u8 messagePublishpority = 0;

ProtocolCtrlStru  ProtocolCtrl = {
    .protoColSend = NULL,
    .protoColFind = ProtoColFindFunc,
    .isData = 0,
    .protocolBuf = {0},
    .protocolTxBuf = {0},
    .protocolRecLen = 0,
};

void ProtocolCheckConnectId(u8 *data, u16 len);
void ProtocolSetConnectId(u8 *data, u16 len);
void ProtocolDownLoadData(u8 *data, u16 len);
void ProtocolCheckConfig(u8 *data, u16 len);
void ProtocolSetConnectStatus(u8 *data, u16 len);

ProtocolFuncStru g_ProtocolFunc[] = {
    {FUNCODEL_CONNECT, FUNCODEH_UDATA_ID,           ProtocolCheckConnectId},
    {FUNCODEL_CONNECT, FUNCODEH_SET_ID,             ProtocolSetConnectId},
    {FUNCODEL_CONNECT, FUNCODEH_UDATACONFIG,        ProtocolCheckConfig},
    {FUNCODEL_CONNECT, FUNCODEH_SET_CONNECTSTATE,   ProtocolSetConnectStatus},
    {FUNCODEL_CONNECT, FUNCODEH_DOWNLOAD_DATA,      ProtocolDownLoadData},
    {0, 0, NULL}
};

/************查询连接ID*****************/
void ProtocolCheckConnectId(u8 *data, u16 len)
{
    u8 id = 0;
    ProtoColSend(&ProtocolCtrl, FUNCODEL_CONNECT, FUNCODEH_UDATA_ID, &id, sizeof(id));
}

/************查询配置*****************/
void ProtocolCheckConfig(u8 *data, u16 len)
{
    u8 buf[4] = {0};
    ProtoColSend(&ProtocolCtrl, FUNCODEL_CONNECT, FUNCODEH_UDATACONFIG, buf, sizeof(buf));
}

/************设置连接状态*****************/
void ProtocolSetConnectStatus(u8 *data, u16 len)
{
    u8 status = STATE_OK;
    // ProtoColSend(&ProtocolCtrl, FUNCODEL_CONNECT, FUNCODEH_SET_ID, &status, sizeof(status));
    myPrint("set status\r\n");    
}

/************设置ID*****************/
void ProtocolSetConnectId(u8 *data, u16 len)
{
    u8 status = STATE_OK;
    u8 id = data[0];
    // ProtoColSend(&ProtocolCtrl, FUNCODEL_CONNECT, FUNCODEH_SET_ID, &status, sizeof(status));
    myPrint("set id\r\n");
}

u8 testbuf[50] = {0};
/************下发数据D*****************/
void ProtocolDownLoadData(u8 *data, u16 len)
{
    u8 status[2] = {0, 1};
    for( u16 i = 0; i < len; i++){
        testbuf[i] = data[i];
    }
    ProtoColSend(&ProtocolCtrl, FUNCODEL_CONNECT, FUNCODEH_DOWNLOAD_DATA, &status, sizeof(status));
    unsigned int box_data = (data[1] << 8) | data[0];
    for (int i = 0; i < 12; i++) {
        box_data <<= 1;
    }
    // myPrint("box_data:%#x\r\n", box_data);

}


void ProtoColInit(ProtocolCtrlStru  *ctrl, sendfunc p, printfFun func)
{
    ctrl->protoColSend = p;
    myPrint = func;
}

ProtocolCtrlStru* ProtocolGetCtrl(void)
{
  return &ProtocolCtrl;
}

u8 ProtoColCheckSum(u8 *data, u16 len)
{
    u32 sum = 0;
    for( u16 i = 0; i < len; i++){
        sum += data[i];
    }
    return sum&0xff;
}

u8 ProtoColGetData(ProtocolCtrlStru  *ctrl, u8 *data, u16 len)
{
    if(len > 512){
        return 1;
    }
    memcpy(ctrl->protocolBuf, data, len);
    ctrl->isData = 1;
    ctrl->protocolRecLen = len;
    return 0;
}

u8 ProtoColGetDataByHttp(ProtocolCtrlStru  *ctrl, u8 cmdIndex, u8 *data, u16 len)
{
    if(len > 512){
        return 1;
    }

    ctrl->currIndex = cmdIndex;
    memcpy(ctrl->protocolBuf, data, len);
    ctrl->isData = 1;
    ctrl->protocolRecLen = len;
    return 0;
}

u8 ProtoColSend(ProtocolCtrlStru  *ctrl, u8 funcode_l, u8 funcode_h, u8* data, u16 len)
{
    if( ctrl->protoColSend == NULL){
        return 1;
    }

    u16 i = 0;
    ctrl->protocolTxBuf[0] = (u8)(ctrl->currIndex & 0xff);
    ctrl->protocolTxBuf[1] = (u8)((ctrl->currIndex >> 8) & 0xff);
    ctrl->protocolTxBuf[2] = 1;
    ctrl->protocolTxBuf[3] = (u8)(PROTOCOLSENDLEN(len)&0xff);
    ctrl->protocolTxBuf[4] = (u8)((PROTOCOLSENDLEN(len)>>8)&0xff);
    ctrl->protocolTxBuf[5] = funcode_l;
    ctrl->protocolTxBuf[6] = funcode_h;
    for(i= 0; i < len; i++){
        ctrl->protocolTxBuf[7+i] = data[i];
    }
    u8 checksum = ProtoColCheckSum((u8*)&ctrl->protocolTxBuf, PROTOCOLSENDLEN(len));
    ctrl->protocolTxBuf[PROTOCOLSENDLEN(len)] = checksum;
    
    ctrl->protoColSend((u8*)&ctrl->protocolTxBuf, PROTOCOLSENDLEN(len) + 1);
    return 0;
}

protocolfunc ProtoColFindFunc(u8 funcode_l, u8 funcode_h)
{
    for(u8 i = 0; i < sizeof(g_ProtocolFunc); i++){
        if((g_ProtocolFunc[i].funcode_l == funcode_l) &&
           (g_ProtocolFunc[i].funcode_h == funcode_h)){
            return g_ProtocolFunc[i].func;
        }
    }
    return NULL;
}

void PrintfPater(u8 *data, u16 len)
{
  myPrint("start\r\n");
  for(u8 i = 0; i < len; i++){
      myPrint("%c", data[i]);
  }
  myPrint("end\r\n");
}

void ProtoColTask(ProtocolCtrlStru  *ctrl)
{
    u16 len = 0;

    if(ctrl->isData != 1){
        return;
    }

    ctrl->isData = 0;
    ProtocolStru *Protocol = (ProtocolStru*)ctrl->protocolBuf;
    if(Protocol->begin != PROTOCOLBEGIN){
        // myPrint("head err\r\n");
        PrintfPater(ctrl->protocolBuf, ctrl->protocolRecLen);
        return;
    }
    u8 checksum = 0;
    u16 reclen = Protocol->len_l | (Protocol->len_h<<8);
    if(reclen < 5){
        memset(ctrl->protocolBuf, 0, sizeof(ctrl->protocolBuf));
        myPrint("len err\r\n");
        return;
    }
    u16 datalen = PROTOCOLDATALEN(reclen);
    checksum = Protocol->data[datalen];
    if(checksum != ProtoColCheckSum((u8*)Protocol, reclen)) {
        memset(ctrl->protocolBuf, 0, sizeof(ctrl->protocolBuf));
        myPrint("checksum err\r\n");
        return;
    }
    protocolfunc func = ctrl->protoColFind(Protocol->funcode_l, Protocol->funcode_h);
    func(Protocol->data, datalen); 
    memset(ctrl->protocolBuf, 0, sizeof(ctrl->protocolBuf));
    return;
}
